﻿// -------------------------------------------------------------------------
//    @FileName         :    NFHeroAttrCalcFactory.cpp
//    @Author           :    Gao.Yi
//    @Date             :    2025-09-30
//    @Email			:    445267987@qq.com
//    @Module           :    NFHeroAttrCalcFactory
//    @Desc             :
//
// -------------------------------------------------------------------------

#include "NFHeroAttrCalcFactory.h"

#include "NFCeUtil.h"
#include "proto_common_hero.nanopb.h"
#include "NFLogicCommon/NFHeroAttrCalc.h"
#include "DescStore/ActorDesc.h"
#include "NFLogicCommon/NFCommMacros.h"
#include "NFLogicServer/NFLogicServerPlayerPlugin/Player/NFPlayer.h"

NFIHeroAttrCalc* NFHeroAttrCalcFactory::Create(HeroOne* pHero, NFPlayer* pPlayer, int64_t llLevel, int64_t llExpSum, RoleCEData* pCEData)
{
    CHECK_NULL_RE_NULL(0, pHero, "");

    auto pHeroDesc = ActorDesc::Instance()->GetDesc(pHero->id);
    CHECK_EXPR(pHeroDesc, NULL, "");

    CHeroBaseAttrCalc* pBaseCalculator = new CHeroBaseAttrCalc(pHero, nullptr, pHeroDesc, llLevel, llExpSum);

    CHeroTotalAttrCalculator* pTotalCalculator = new CHeroTotalAttrCalculator(pHero, pBaseCalculator, pHeroDesc, pCEData);

    return pTotalCalculator;
}

int NFHeroAttrCalcFactory::Calc(HeroOne* pHero, NFPlayer* pPlayer, int64_t llLevel, int64_t llExpSum, RoleCEData* pCEData)
{
    CHECK_NULL(0, pHero);

    NFIHeroAttrCalc* pCalculator = Create(pHero, pPlayer, llLevel, llExpSum, pCEData);
    CHECK_NULL(0, pCalculator);

    int iRet = pCalculator->Exec();

    delete pCalculator;

    return iRet;
}

int NFHeroAttrCalcFactory::UpdateHP(HeroOne* pHero, NFPlayer* pPlayer, int64_t llBeforeVal)
{
    CHECK_NULL(0, pHero);
    int64_t llHp = pHero->attr_list[proto_ff::EN_ATTR_HP].value;
    int64_t llMaxHp = pHero->attr_list[proto_ff::EN_ATTR_MAX_HP].value;

    if (llHp > 0 && llBeforeVal > 0)
    {
        int iHpFinal = llHp; //(int64_t)iMaxHp*iHp/iBeforeVal;

        if (iHpFinal > llMaxHp)
        {
            iHpFinal = llMaxHp;
        }

        if (iHpFinal <= 0)
        {
            iHpFinal = 1;
        }

        pHero->attr_list[proto_ff::EN_ATTR_HP].value = iHpFinal;
    }

    return 0;
}

int NFHeroAttrCalcFactory::UpdateMP(HeroOne* pHero, NFPlayer* pPlayer, int64_t llBeforeVal)
{
    int64_t llMp = pHero->attr_list[proto_ff::EN_ATTR_MP].value;
    int64_t llMaxMp = pHero->attr_list[proto_ff::EN_ATTR_MAX_MP].value;

    if (llMp > 0 && llBeforeVal > 0)
    {
        int iMpFinal = llMp; //(int64_t)iMaxMp*iMp/iBeforeVal;

        if (iMpFinal > llMaxMp)
        {
            iMpFinal = llMaxMp;
        }

        if (iMpFinal < 0)
        {
            iMpFinal = 0;
        }

        pHero->attr_list[proto_ff::EN_ATTR_MP].value = iMpFinal;
    }

    return 0;
}

int NFHeroAttrCalcFactory::Recalc(HeroOne* pHero, NFPlayer* pPlayer, bool bEvent)
{
    int64_t llBeforeMaxHP = pHero->attr_list[proto_ff::EN_ATTR_MAX_HP].value;
    int64_t llBeforeMaxMP = pHero->attr_list[proto_ff::EN_ATTR_MAX_MP].value;

    int iRet = Calc(pHero, pPlayer, pHero->attr_list[proto_ff::EN_ATTR_LEVEL].value / ATTR_VALUE_MULTI, pHero->attr_list[proto_ff::EN_ATTR_EXP_SUM].value, pPlayer ? NFCeUtil::GetCeData(pPlayer): nullptr);
    CHECK_RET(iRet, "calc attr failed.");

    if (llBeforeMaxHP != pHero->attr_list[proto_ff::EN_ATTR_MAX_HP].value)
    {
        UpdateHP(pHero, pPlayer, llBeforeMaxHP);
    }

    if (llBeforeMaxMP != pHero->attr_list[proto_ff::EN_ATTR_MAX_MP].value)
    {
        UpdateMP(pHero, pPlayer, llBeforeMaxMP);
    }

    if (pPlayer)
    {
        /*RoleCEData stCEData = *( pPlayer->GetCEExt()->GetData() );
        pPlayer->GetCEExt()->CopyFromTemp();

        proto_ff_s::RoleCEData_s* pCEData = pPlayer->GetCEExt()->GetData();
        CHECK_NULL(pCEData);

        if(stCEData.ce_list[proto_ff::EN_CE_TYPE_GEMSTONE] != pCEData->ce_list[proto_ff::EN_CE_TYPE_GEMSTONE])
        {
            CEventDisp::OnCEScoreUpdate(pPlayer,pCEData->ce_list[proto_ff::EN_CE_TYPE_GEMSTONE],1);
        }

        if(stCEData.ce_list[proto_ff::EN_CE_TYPE_EQUIP] != pCEData->ce_list[proto_ff::EN_CE_TYPE_EQUIP])
        {
            CEventDisp::OnCEScoreUpdate(pPlayer,pCEData->ce_list[proto_ff::EN_CE_TYPE_EQUIP],2);
        }

        if(stCEData.ce_list[proto_ff::EN_CE_TYPE_PARTNER] != pCEData->ce_list[proto_ff::EN_CE_TYPE_PARTNER])
        {
            CEventDisp::OnCEScoreUpdate(pPlayer,pCEData->ce_list[proto_ff::EN_CE_TYPE_PARTNER],3);
        }*/
    }

    if (bEvent)
    {
        //CEventDisp::OnHeroAttrChanged( pPlayer, proto_ff::EN_ATTR_MIN );
    }

    return 0;
}
